/*
Java board game library.
Copyright (C) 2011  Deepesh Garg

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package d.g.boardgames.chess;

import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import d.g.boardgames.GameData;
import d.g.boardgames.MoveData;
import d.g.boardgames.chess.ChessCellState.PieceColor;


public class ChessGameData extends GameData<ChessBoard, ChessMove> {

	public String getPgn() {
		String gameString = "";
		PGNMoveParser pgnMoveParser = new PGNMoveParser();
		FENSerializer fenSerializer = new FENSerializer();
		
		int moveNumber = 1;
		MoveData<ChessBoard, ChessMove> startingPosition = moveDataList.get(0);
		if (startingPosition.getBoard() != null) {
			String startingPositionFen = fenSerializer.getString(startingPosition.getBoard());
			gameString += "[FEN \"" + startingPositionFen + "\"]\n\n";
			if (startingPosition.getBoard().getTurn() == PieceColor.BLACK) {
				gameString += (moveNumber++) + "... ";
			}
		}
		
		//for (MoveData<ChessBoard, ChessMove> moveData: moveDataList) {
		for (int i=0; i < moveDataList.size(); i++) {
			MoveData<ChessBoard, ChessMove> moveData = moveDataList.get(i);
			ChessBoard board = moveData.getBoard();
			ChessMove move = moveData.getMove();
			if (board != null && move != null) {
				String moveString = "";
				String fen = "";
				gameString += "\n";
				if (board.getTurn() == PieceColor.WHITE) {
					moveString += (moveNumber++) + ". ";
				} else {
					moveString += "    ";
				}
				moveString += pgnMoveParser.createMoveString(board, move);
				gameString += moveString + " ";
				String analysisString = "";
				if (board.getAnalysisData() != null) {
					if ((i+1) < moveDataList.size()) {
						MoveData<ChessBoard, ChessMove> nextMoveData = moveDataList.get(i+1);
						if (nextMoveData.getBoard() != null) {
							board.getAnalysisData().setFen(fenSerializer.getString(nextMoveData.getBoard()));
							gameString += "{ " +   board.getAnalysisData().getString() + " } ";
						}
					}
				}
			}
		}
		return gameString;
	}
	
	public void fromPgn (String pgnString) {
		Pattern p = Pattern.compile ("\\[FEN\\s+\"(.*)\"\\]");
		Matcher m = p.matcher(pgnString);
		ChessBoard startBoard = new ChessBoard();
		if (m.find()) {
			String fen = m.group(1);
			FENSerializer fenSerializer = new FENSerializer();
			startBoard = fenSerializer.getBoard(fen);
		}
		
		p = Pattern.compile ("\\[\\S+\\s+\".*\"\\]");
		m = p.matcher(pgnString);
		int index = 0;
		while (m.find()) {
			index = m.end();
		}
		
		p = Pattern.compile("(?:\\d+\\.)?(?:\\.\\.)?\\s*(\\S+)\\s*(?:\\{([^\\}]*)\\})?\\s*");
		m = p.matcher(pgnString);
		boolean matchFound = m.find(index);
		index = 0;
		
		moveDataList.clear();
		MoveData<ChessBoard, ChessMove> moveData = new MoveData<ChessBoard, ChessMove>(startBoard, null);
		moveDataList.add(moveData);
		CoordinateMoveParser coordinateMoveParser = new CoordinateMoveParser();
		PGNMoveParser pgnMoveParser = new PGNMoveParser();
		FENSerializer fenSerializer = new FENSerializer();
		ChessGameData nextHint = null;
		while (matchFound) {
			try {
				String moveString = m.group(1);
				System.out.println(moveString);
				ChessMove chessMove;
				chessMove = coordinateMoveParser.parseMoveString(getLastEntry().getBoard(), moveString);
				if (chessMove == null) {
					chessMove = pgnMoveParser.parseMoveString(getLastEntry().getBoard(), moveString);
				}
				ChessBoard board = getLastEntry().getBoard().move(chessMove);
				if (getLastEntry().getBoard().getTurn() != board.getTurn()) {
					getLastEntry().setMove(chessMove);
					if (m.group(2) != null) {
						AnalysisData ad = new AnalysisData();
						ad.fromString(m.group(2), null);
						if (ad.getWhiteScore() != AnalysisData.NOT_SET) {
							getLastEntry().getBoard().setAnalysisData(ad);	
						}
						if (nextHint != null) {ad.setHint(nextHint); nextHint = null;}
						String fen = fenSerializer.getString(getLastEntry().getBoard());
						if (ad.getComment()!= null) {
							String hintPgn = "[FEN \"" + fen + "\"]\n" + ad.getComment();
				        	ChessGameData gameData = new ChessGameData();
				        	gameData.fromPgn(hintPgn);
				        	getLastEntry().getBoard().getAnalysisData().setHint(gameData);
						}
					}
					moveData = new MoveData<ChessBoard, ChessMove>(board, null);
					moveDataList.add(moveData);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			matchFound = m.find();
		}
	}
}
